• 问题

    在16条中阐述了贸然的将不是为了继承而设计的类进行继承,而实现子类化,是多么的危险,那么,在实际开发中,针对继承而设计的类怎样的处理才算是安全可靠的?

  • 解决

    1. 对于专门为了继承而设计并且具有良好文档说明的类而言,该类的文档必须精确地描述覆盖每个方法所带来的影响。该类必须有文档说明它可覆盖的方法的自用性。对于每个公有的或受保护的方法或者构造器,它的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的。更一般的,类必须在文档中说明,在哪些情况下它会调用可覆盖的方法。
    2. 关于程序文档的格言:好的API文档应该描述一个给定的方法做了什么工作,而不是描述它是如何做到的。由此看来,上面的这段文档违背了这一格言,这正是继承破坏了封装性所带来的不幸后果,因为在上面这段文档中它必须要说明清楚调用可覆盖方法所带来的影响。所以,为了设计一个类的文档,以便它能够被安全的子类化,必须描述清楚那些有可能未定义的实现细节
    3. 还要注意,因继承而需要的特殊文档会打乱正常的文档信息,普通的文档被设计用来让程序员可以创建该类的实例,并调用类的方法。而特殊文档看起来混用了很多内容。为了允许继承,类还必须遵守其他的一些约束。构造器决不能调用可被覆盖的方法,无论是直接调用还是间接调用。这是因为超类的构造器在子类的构造器之前运行,所以,子类中覆盖版本的方法将会在子类的构造器运行之前就先被调用。如果该覆盖版本的方法信赖于子类构造器所执行的任何初始化操作,该 方法将不会如预期执行;
    4. 对于那些并非为了安全地进行子类化而设计和编写文档的类,要禁止子类化。有两种办法可以禁止子类化:第一,把这个类声名为final。第二、把所有的构造器都声名为private,或者包级私有并增加一些静态工厂来替代构造器。
  • 结论

    1. 如果具体的类没有实现标准的接口,那么禁止继承可能会给有些程序员带来不便,如果认为必须允许从这样的类继承,一种合理的办法就是确保这个类永远不会调用它的任何可覆盖的方法,并在文档中说明这一点。否则,就禁止被子类化。
    2. 针对自用性问题,也可以机械的消除类中可覆盖方法的自用特征,而不改变它们的行为。将每个可覆盖方法的代码体移动到一个私有的辅助方法中。并且让每个可覆盖的方法调用它的私有辅助方法。然后,用”直接调用可覆盖方法的私有辅助方法“来代替”可覆盖方法的每个自用调用“。

results matching ""

    No results matching ""